/*
 * sequential_file.c
 *
 *  Created on: Mar 31, 2012
 *      Author: lin
 */

#include <errno.h>
#include <assert.h>
#include <stdint.h>
#include "zmalloc/zmalloc.h"
#include "io.h"

#include "sequential_file.h"

sequential_file_t* seq_file_open0(const char *name, FILE *fp) {
    sequential_file_t *seqfile = zmalloc(sizeof(sequential_file_t));
    seqfile->fname = name ? zstrdup(name) : NULL;
    seqfile->fp = fp;
    return seqfile;
}

sequential_file_t* seq_file_open1(const char *name, const char *mode) {
    assert(name);
    FILE *fp = fopen(name, mode);
    if (fp) {
        return seq_file_open0(name, fp);
    }
    return NULL;
}

void seq_file_close(sequential_file_t *file) {
    if (file->fname) {
        zfree((void *) file->fname);
    }
    fclose(file->fp);
    zfree(file);
}

int seq_file_read(const sequential_file_t *file, size_t n, char *buf,
        size_t *readed) {
    return io_fread_unlocked(file->fp, sizeof(char), n, (void*) buf, readed);
}

int seq_file_write(const sequential_file_t *file, size_t n, const char *buf) {
    return io_fwrite_unlocked(file->fp, sizeof(char), n, buf);
}

int seq_file_seek(const sequential_file_t *file, int64_t n) {
    assert(n >= 0);
    if (fseeko(file->fp, n, SEEK_CUR)) {
        return errno;
    }
    return 0;
}

int seq_file_tell(const sequential_file_t *file, int64_t *n) {
    int64_t off = ftello(file->fp);
    if (off == -1) {
        return errno;
    }
    *n = off;
    return 0;
}
